import time

import can
from typing import Optional
import queue
from multiprocessing import Queue


class CanTool:

    def __init__(self, device: Optional[str], channel: Optional[str], bit_rate: Optional[int]):
        """
        初始化类时即创建总线对象
        param1：设备名
        param2：通道名
        param3：波特率
        """
        # 是否在初始化时创建对象基于项目而定
        self.__bus = can.interface.Bus(bustype=device, channel=channel, bitrate=bit_rate)
        self.mq = Queue()
        # 创建一个log文件
        logger = can.Logger("logfile.asc")
        listeners = [
            self.__put_mq,  #回调函数
            logger,  # 保存报文的对象
        ]
        # 设置一个监听
        self.notifier = can.Notifier(self.__bus, listeners)

    def __put_mq(self, msg):
        """
        功能：通过队列实现数据的写入和读取
        :param msg: 回调返回的对象
        """
        if not self.mq.full():
            self.mq.put_nowait(msg)

    def send_data(self, id: Optional[int], list_data: Optional[int]):
        msg = can.Message(arbitration_id=id,#此处传入整形
                          is_extended_id=False, #此处参数判断是否是扩展帧
                          data=list_data #此处参数传入一个纯整形的列表
                          )
        self.__bus.send(msg)

    def set_filters(self, filter_id: Optional[int]):
        """
        功能：设置一个筛选器
        para1：报文id
        """
        if filter_id < 2147483648:#判断是否为标准帧
            self.__bus.set_filters([{"can_id": filter_id, "can_mask": 0x7FF, "extended": False}])
        else:
            self.__bus.set_filters([{"can_id": filter_id, "can_mask": 0x1FFFFFFF, "extended": True}])

    def can_recv(self, filter_id: Optional[int]):
        """
        循环检测接收到的报文中是否有需要的id
        para1：报文id
        """
        while True:
            if not self.mq.empty():
                frame = self.mq.get_nowait()
                if filter_id == frame.arbitration_id:
                    print(frame.data)
                    break
            time.sleep(0.1)



